package homework10package;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;

/**
 * pageRank class
 * 
 * this class provides methods for searching the database
 * 
 * @author      Lisa Park and Orion Taylor
 * @course Software Engineering
 * @date 2-2-13
 */

public class Query {
	
	public static void main(String args [])
			throws ClassNotFoundException, IOException{
		
		Query searcher=new Query();
		
		System.out.println(searcher.searchTerm("variable"));
	}
	
	/**searchTerm()
	 * 
	 * this function takes in a list of search terms and returns an ArrayList
	 * of URL's that contain all of the search terms
	 * 
	 * these URL's are ordered using page rank
	 * 
	 * if the search is not in the database, this function returns null
	 * 
	 * @param terms: a list of the search terms we care about
	 * 
	 * @return ArrayList <String> : URL's that we have found for the given
	 * search term
	 * 
	 * @throws IOException 
	 * @throws ClassNotFoundException 
	 */
	public ArrayList <String> searchTerms(ArrayList<String> terms)
			throws ClassNotFoundException, IOException{
		
		//if there are no terms to search through
		if(terms.size()==0){
			//return nothing
			return null;
		}
		
		//for each search term
		for(int i=0;i<terms.size();i++){
			//make the term lower case (since all terms are store lower case)
			terms.set(i, terms.get(i).toLowerCase());
		}

		//retrieve the database and store it in myIndex
		Indexer myIndexer=new Indexer();
	    Index myIndex = myIndexer.retrieveDatabase();
	    
	    //iterate through terms
	    for(String term:terms){
		    //if the search term does not exist, return null
		    if(!myIndex.getTerm_index().containsKey(term)){
		    	return null;
		    }
	    }
	    
	    
	    //urlSet is the set of urls with pages that contain all of the terms
	    HashSet <Integer> urlSet=new HashSet<Integer>();
	    
	    //set urlSet to contain the urls that contain the first term
	    urlSet.addAll(myIndex.getBackward_term_map().
	    		get(myIndex.getTerm_index().get(terms.get(0))).keySet());
	    
	    for(String term:terms){
	    	//tempSet is a set that will contain all urls that
	    	//contain the previous terms AND the current term
		    HashSet <Integer> tempSet=new HashSet<Integer>();
		    
		    //iterate through all the urls that contain the current term
		    for(Integer url:myIndex.getBackward_term_map().
		    		get(myIndex.getTerm_index().get(term)).keySet()){
		    	
		    	//if the url also contained all of the previous terms..
		    	if(urlSet.contains(url)){
		    		//add it to tempSet
		    		tempSet.add(url);
		    	}
		    }
		    
		    //set urlSet to tempSet, then repeat for all terms
		    urlSet=tempSet;
	    }
	    
	    //urls represents the integer codes corresponding to the 
	    //urls that have the search term on their page
	    ArrayList<Integer> urls = new ArrayList <Integer>();
	    urls.addAll(urlSet);
	    
	    //sort the urls by page rank
	    this.sortbyRank(urls, myIndex);
	    
	    //return url_String
        return nameUrls(urls, myIndex);
	  
	}
	
	/**searchTerm()
	 * 
	 * this function takes in a search term and returns an ArrayList
	 * of URL's that this search term is found on
	 * 
	 * these URL's are ordered using page rank
	 * 
	 * if the search is not in the database, this function returns null
	 * 
	 * @param term: the search term we care about
	 * 
	 * @return ArrayList <String> : URL's that we have found for the given
	 * search term
	 * 
	 * @throws IOException 
	 * @throws ClassNotFoundException 
	 */
	public ArrayList <String> searchTerm(String term)
			throws ClassNotFoundException, IOException{
		
		//Wrap the single term in an ArrayList
		ArrayList <String> wrapperList=new ArrayList<String>();
		wrapperList.add(term);
		
		//call the searchTerms function for this wrapped term
		return this.searchTerms(wrapperList);
	}

	/**This function maps a list of Integers representing URL codes
	 * to a list of strings representing the url names
	 * 
	 * @param urls: the list of url codes that we want decoded
	 * @param myIndex: a representation of our web index
	 * @return ArrayList<String>: a list of the url names
	 */
	private ArrayList<String> nameUrls(ArrayList<Integer> urls, Index myIndex) {
		//url_String represents the urls that have the search term
        //on their page
	    ArrayList<String> url_String= new ArrayList <String> ();
	    
	    //decode the integer codes in urls, and put the result in url_string
	    for(int i=0; i< urls.size(); i++){
	    	url_String.add(myIndex.getReverse_url_index().get(urls.get(i)));
	    }
	  //return url_String
		return url_String;
	}
	
	/**sortbyRank
	 * 
	 * this function sorts a set of URL's by page rank
	 * 
	 * @param urls: the list of urls that we want to sort
	 * @param myIndex: a representation of our web index 
	 */
	private void sortbyRank(ArrayList<Integer> urls, Index myIndex){
		 //sort the urls by page rank
        for (int i = 0; i < urls.size(); i ++){
            for (int j = i; j< urls.size(); j++){
                if (myIndex.getUrlRank().get(urls.get(i)).doubleValue()
                < myIndex.getUrlRank().get(urls.get(j)).doubleValue()){
                	
                    Integer temp = urls.get(i);
                    urls.set(i,urls.get(j));   
                    urls.set(j,temp);
                }
            }
        }
	}
	

	
}
